package com.woniu.elderly.serve.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniu.common.dto.ServePersonDTO;
import com.woniu.common.entity.DealOrder;
import com.woniu.common.entity.ServeAudit;
import com.woniu.common.entity.ServePerson;
import com.woniu.common.entity.ServeWorkOrder;
import com.woniu.elderly.serve.feignclient.DealOrderFeign;
import com.woniu.elderly.serve.mapper.ServePersonMapper;
import com.woniu.elderly.serve.service.ServeAuditService;
import com.woniu.elderly.serve.service.ServePersonService;

import com.woniu.elderly.serve.service.ServeWorkOrderService;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;

import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class ServePersonServiceImpl extends ServiceImpl<ServePersonMapper, ServePerson> implements ServePersonService {
    @Autowired
    private ServeAuditService serveAuditService;

    @Autowired
    private ServeWorkOrderService serveWorkOrderService;

    @Autowired
    private DealOrderFeign dealOrderFeign;

    @Autowired
    private RedisTemplate redisTemplate;

    //查询全部
    @Override
    @Transactional(isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Page<ServePerson> findAll(int pageIndex, int pageSize, ServePersonDTO servePersonDTO) {
        Wrapper<ServePerson> wrapper = new LambdaQueryWrapper<>(ServePerson.class)
                .like(!StringUtils.isEmpty(servePersonDTO.getPname()), ServePerson::getPname, servePersonDTO.getPname())//姓名模糊条件
                .eq(!StringUtils.isEmpty(servePersonDTO.getGender()), ServePerson::getGender, servePersonDTO.getGender())//性别条件
                .eq(servePersonDTO.getAge() != null, ServePerson::getAge, servePersonDTO.getAge())//年龄条件
                .eq(!StringUtils.isEmpty(servePersonDTO.getServetype()), ServePerson::getServetype, servePersonDTO.getServetype())//服务类型条件
                .like(!StringUtils.isEmpty(servePersonDTO.getArea()), ServePerson::getArea, servePersonDTO.getArea())//服务区域条件
                .eq(!StringUtils.isEmpty(servePersonDTO.getState()), ServePerson::getState, servePersonDTO.getState())//状态条件
        ;
        Page<ServePerson> servePersonPage = baseMapper.selectPage(new Page<ServePerson>(pageIndex, pageSize), wrapper);
        servePersonPage.getRecords().forEach(servePerson -> {
            if (servePerson.getAid() == 0) {
                servePerson.setServeAudit(new ServeAudit(null, null, "无审核", null, null, null, null, null, null));
            } else {
                servePerson.setServeAudit(serveAuditService.findById(servePerson.getAid()));
            }
        });

        return servePersonPage;
    }

    @Override
    public List<ServePerson> findAll() {
        return baseMapper.selectList(null);
    }

    //根据id查询
    @Override
    public ServePerson findById(int id) {
        return baseMapper.selectById(id);
    }

    //添加服务人员
    @Override
    @GlobalTransactional(name = "fsp_tx_group",rollbackFor = Exception.class)
    public String add(ServePerson servePerson) {
        //将int类型转换成string类型，不够位补0
        String jobNumber = new DecimalFormat("000000").format(getJobNumber());

        //返回给前端一个提示信息
        String str = "<spen>您的工号：" + jobNumber + "<br>您的密码：aaa<br>您可以使用工号+密码登录后台系统!!!</spen>";
        servePerson.setJobnumber(jobNumber);
        servePerson.setPassword(DigestUtils.md5DigestAsHex("aaa".getBytes()));
        servePerson.setState("空闲");
        baseMapper.insert(servePerson);

        //将服务人员信息添加至后端登录系统

        return str;
    }

    //获取工号
    private int getJobNumber(){
        SetOperations<String, Integer> opsForSet = redisTemplate.opsForSet();

        //查询redis中有没有工号
        if(opsForSet.size("jobNumber") <= 0) {
            //获取全部的工号
            List<ServePerson> servePeople = baseMapper.selectList(
                    Wrappers
                            .<ServePerson>lambdaQuery()
                            .select(ServePerson::getJobnumber)
                            .last("or del in (0,1)")
            );

            //获取最大工号
            int max = 0;
            for(int i = 1; i < servePeople.size(); i++){
                max = Integer.parseInt(servePeople.get(0).getJobnumber());
                if(Integer.parseInt(servePeople.get(i).getJobnumber()) > max){
                    max = Integer.parseInt(servePeople.get(i).getJobnumber());
                }
            }
            max++;
            int redisJob = max + 1;
            opsForSet.add("jobNumber", redisJob);
            return max;
        }else{
            //获取redis中的工号发回，并加一存入redis
            int jobNumber = opsForSet.pop("jobNumber");
            int redisJob = jobNumber + 1;
            opsForSet.add("jobNumber", redisJob);
            return jobNumber;
        }
    }

    //修改服务人员
    @Override
    public void modify(ServePerson servePerson) {
        baseMapper.updateById(servePerson);
    }

    //离职申请
    @Override
    @Transactional(isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void apply(int id, String cause) {
        //获取当前系统时间作为离职申请时间
        Date date = new Date();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String time = dateFormat.format(date);

        //添加审核
        ServeAudit serveAudit = new ServeAudit();
        serveAudit.setAuditcontent("离职申请,离职原因:" + cause);
        serveAudit.setApplytime(time);
        serveAudit.setPid(id);

        int aid = serveAuditService.add(serveAudit);

        //修改状态
        ServePerson servePerson = new ServePerson();
        servePerson.setPid(id);
        servePerson.setState("离职审核");
        servePerson.setAid(aid);

        /*if(true){
            throw new RuntimeException("离职申请异常");
        }*/

        //将服务人员的id从redis中移除
        SetOperations<String, Integer> opsForSet = redisTemplate.opsForSet();
        opsForSet.remove("ids", servePerson.getPid());

        baseMapper.updateById(servePerson);
    }

    //撤销申请
    @Override
    @Transactional(isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void revocation(ServePerson servePerson) {
        //修改审核
        ServeAudit serveAudit = new ServeAudit();
        serveAudit.setAid(servePerson.getAid());
        serveAudit.setState("撤销");

        serveAuditService.modify(serveAudit);
        serveAuditService.remove(serveAudit.getAid());

        servePerson.setState("空闲");
        servePerson.setAid(0);

        //将服务人员的id存入redis
        SetOperations<String, Integer> opsForSet = redisTemplate.opsForSet();
        opsForSet.add("ids", servePerson.getPid());

        /*if(true){
            throw new RuntimeException("撤销申请异常");
        }*/

        baseMapper.updateById(servePerson);
    }

    //删除服务人员
    @Override
    public void remove(int id) {
        baseMapper.deleteById(id);
    }

    //随机抽一位服务人员id
    @Override
    public int random(String serveType) {
        SetOperations<String, Integer> opsForSet = redisTemplate.opsForSet();
        //查询redis中有没有ids
        if(opsForSet.size("ids") <= 0) {
            initRedis();
        }

        try{
            int id = opsForSet.pop("ids");
            //判断此id的服务人员的服务类型是否匹配
            if(baseMapper.selectById(id).getServetype().equals(serveType)){
                return id;
            }else {
                opsForSet.add("ids", id);
                return random(serveType);
            }
        }catch (StackOverflowError e){
            initRedis();
            return 0;
        }catch (Exception e){
            initRedis();
            return 0;
        }
    }

    //初始化redis数据
    private void initRedis(){
        SetOperations<String, Integer> opsForSet = redisTemplate.opsForSet();
        //获取所有空闲的人员id
        int[] ids = baseMapper.selectIdArr();
        //遍历id并存入redis
        for (int id : ids) {
            opsForSet.add("ids", id);
        }
    }

    //服务人员完成服务
    @Override
    @GlobalTransactional(name = "fsp_tx_group",rollbackFor = Exception.class)
    public void finish(ServePerson servePerson) {
        //获取当前系统时间作为完成服务的时间
        Date date = new Date();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String time = dateFormat.format(date);

        //修改工单内容
        ServeWorkOrder serveWorkOrder = new ServeWorkOrder();
        serveWorkOrder.setWid(servePerson.getWid());
        serveWorkOrder.setEndtime(time);
        serveWorkOrder.setState("已完成");
        serveWorkOrderService.modify(serveWorkOrder);

        //修改服务人员内容
        servePerson.setState("空闲");
        baseMapper.updateById(servePerson);

        //将服务人员的id存入redis
        SetOperations<String, Integer> opsForSet = redisTemplate.opsForSet();
        opsForSet.add("ids", servePerson.getPid());

        //修改订单内容
        DealOrder dealOrder = new DealOrder();
        dealOrder.setOrderId(serveWorkOrderService.findById(serveWorkOrder.getWid()).getOid());
        dealOrder.setOrderFinishdate(time);
        dealOrderFeign.modify(dealOrder);
    }
}
